37

大概会用一个系列,讲一下面试过程中经常会问的一些问题,以及我觉得应该可以怎么回答。

当然,我的回答也并不是标准答案,只是我自己的一些理解,也欢迎其他人发表自己的想法。

作为本系列的第一篇文章,就先讲讲被问的最多的 js 继承问题,但是应该不会写原型链相关的东西,

先列举一个最简单的问题:

写一个 inherit(superClass, subClass) 方法,实现subClass 继承 superClass

题目隐含的内容

继承有哪些特征,如何检测一个继承是否成功?
  1. 子类可以使用父类的方法和属性
  2. 子类可以自定义方法和属性,但应该不影响父类和其他继承同一个父类的子类
  3. 子类的原型链上可以找到父类(子类的__proto__应指向父类)
  4. 子类的实例可以通过 foo instanceof superClass 测试

常见的解法

es5
function inherit(p, s) {
  s.prototype = Object.create(p.prototype, {
    constructor: {
      value: s,
      enumerable: false,
      writebale: true,
      configurable: true
    }
  })

  Object.setPrototypeOf ? Object.setPrototypeOf(s, p) : s.__proto__ = p
} 
es4
function inherit(p, s) {
  var f = new Function ()
  f.prototype = new p()
  var r = new f()
  s.prototype = r
  s.prototype.constructor = s
  s.__proto__ = p
  f = null
}

引申的问题:

  1. Object.create 是什么?怎么使用?
Object.create(proto, [propertiesObject])

Object.create 提供了一个创建对象的方法,使用现有的对象作为新创建对象的__proto__,同时可以传入添加到新对象的可枚举属性, 这些属性可以对应到Object.defineProperties 的第二个参数中。

返回值为所创建的新对象.

例如:

s.prototype = Object.create(f.prototype, {
  constructor: {
    value: s,
    enumberable: false,
    writealble: true,
    configurale: true
  }
})
  1. Object.defineProperties 是什么?怎么使用?可以列举一个 Object.definProperties 的实际应用吗?

Object.defineProperties可以直接在一个对象上定义或修改属性,并返回该对象。

例如:

target = Object.defineProperties(target, props)

本质上 Object.defineProperties 是对Object.defineProperty 的集中调用,可以理解为是Object.definePeropety的复数版。

Object.defineProperty 的使用方法为:

target = Object.defineProperty(target, prop, descriptor)

所以本质上Object.defineProperties 就是如下代码:

Object.keys(props).forEach(function (prop) {
  let descriptor = props[prop]
  Object.defineProperty(target, prop, descriptor)
})

其中 descriptor 的可选值有以下集中:

  • configurable: 当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为 false
  • enumerable: 当且仅当该属性的enumerable为 true 时,该属性才能够出现在对象的枚举属性中。默认为 false
  • value: 该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined
  • writable: 当且仅当该属性的writable为true时,value才能被赋值运算符改变。默认为 false。
  • get: 一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。该方法返回值被用作属性值。默认为 undefined
  • set: 一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认为 undefined

如果一个 descriptor 不具有 value, writebale, getset 任意一个关键字,那么将会被认为是一个数据描述符。
如果一个描述符同时具有(valuewritbale)和(getset),将会产生一个异常.

  1. 继承多个父类怎么做?

继承多个父类的话,可以使用 Object.assign 方法。
例如:

targe = Object.assign({}, superClassA, superClassB, ...)

但是继承多个父类的话,子类就不能通过 son instanceof superClass 这样的验证了.

  1. Object.assign 是什么?怎么用?用的时候有哪些需要注意?

Object.assign 方法用于将所有可枚举属性从一个或多个源对象复制到目标对象,并返回目标对象,例如:

target = Object.assign(target, source)

如果具有同名属性,那么在后面对象中的属性,将会覆盖目标对象中的属性。

需要注意以下几点:

  • 继承属性不可枚举属性是不能拷贝的。
  • 原始类型会被包装为对象,null, undefined 会被忽略,并且只有字符串的包装对象才可能有自身可枚举的属性.
  • 可以拷贝 symbol 类型的属性
  1. Object.assign 会调用 settergetter 吗?调用的是哪里的settergetter ?

Object.assign 会调用源对象的 getter,并把源对象的 getter 的返回值当做新对象的该属性的值。
setter 则是会直接加在新创建的对象中,而不会沿用源对象的 setter.

  1. Object.getOwnPropertyDescriptor 是什么?主要用来做什么?

Object.getOwnPropertyDescriptor 返回直到对象上一个自有属性对应的描述符,例如:

Object.getOwnPropertyDescriptor(obj, prop)

tobeyouth
773 声望9 粉丝